package com.rzl.expense.system.service.impl;

import com.rzl.expense.common.annotation.DataScope;
import com.rzl.expense.common.constant.CacheConstants;
import com.rzl.expense.common.constant.UserConstants;
import com.rzl.expense.common.core.domain.TreeSelect;
import com.rzl.expense.common.core.domain.entity.SysRegion;
import com.rzl.expense.common.core.domain.entity.SysRole;
import com.rzl.expense.common.core.domain.entity.SysUser;
import com.rzl.expense.common.core.redis.RedisCache;
import com.rzl.expense.common.core.text.Convert;
import com.rzl.expense.common.exception.ServiceException;
import com.rzl.expense.common.utils.SecurityUtils;
import com.rzl.expense.common.utils.StringUtils;
import com.rzl.expense.common.utils.spring.SpringUtils;
import com.rzl.expense.system.mapper.SysRegionMapper;
import com.rzl.expense.system.mapper.SysRoleMapper;
import com.rzl.expense.system.service.ISysRegionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 地市管理 服务实现
 *
 * @author expense
 */
@Service
public class SysRegionServiceImpl implements ISysRegionService {
    @Autowired
    private SysRegionMapper regionMapper;

    @Autowired
    private SysRoleMapper roleMapper;

    @Autowired
    private RedisCache redisCache;

    /**
     * 查询地市管理数据
     *
     * @param region 地市信息
     * @return 地市信息集合r
     */
    @Override
    @DataScope(regionAlias = "r")
    public List<SysRegion> selectRegionList(SysRegion region) {
        return regionMapper.selectRegionList(region);
    }

    /**
     * 查询地市树结构信息
     *
     * @param region 地市信息
     * @return 地市树信息集合
     */
    @Override
    public List<TreeSelect> selectRegionTreeList(SysRegion region) {
        List<SysRegion> regions = SpringUtils.getAopProxy(this).selectRegionList(region);
        return buildRegionTreeSelect(regions);
    }

    /**
     * 构建前端所需要树结构
     *
     * @param regions 地市列表
     * @return 树结构列表
     */
    @Override
    public List<SysRegion> buildRegionTree(List<SysRegion> regions) {
        List<SysRegion> returnList = new ArrayList<SysRegion>();
        List<String> tempList = regions.stream().map(SysRegion::getRegId).collect(Collectors.toList());
        for (SysRegion region : regions) {
            // 如果是顶级节点, 遍历该父节点的所有子节点
            if (!tempList.contains(region.getPregId().trim())) {
                recursionFn(regions, region);
                returnList.add(region);
            }
        }
        if (returnList.isEmpty()) {
            returnList = regions;
        }
        return returnList;
    }

    /**
     * 构建前端所需要下拉树结构
     *
     * @param regions 地市列表
     * @return 下拉树结构列表
     */
    @Override
    public List<TreeSelect> buildRegionTreeSelect(List<SysRegion> regions) {
        List<SysRegion> regionTrees = buildRegionTree(regions);
        return regionTrees.stream().map(TreeSelect::new).collect(Collectors.toList());
    }

    /**
     * 根据角色ID查询地市树信息
     *
     * @param roleId 角色ID
     * @return 选中地市列表
     */
    @Override
    public List<String> selectRegionListByRoleId(String roleId) {
        SysRole role = roleMapper.selectRoleById(roleId);
        return regionMapper.selectRegionListByRoleId(roleId, role.isRegionCheckStrictly());
    }

    /**
     * 根据地市ID查询信息
     *
     * @param regionId 地市ID
     * @return 地市信息
     */
    @Override
    public SysRegion selectRegionById(String regionId) {
        return regionMapper.selectRegionById(regionId);
    }

    /**
     * 根据ID查询所有子地市（正常状态）
     *
     * @param regionId 地市ID
     * @return 子地市数
     */
    @Override
    public int selectNormalChildrenRegionById(String regionId) {
        return regionMapper.selectNormalChildrenRegionById(regionId);
    }

    /**
     * 是否存在子节点
     *
     * @param regionId 地市ID
     * @return 结果
     */
    @Override
    public boolean hasChildByRegionId(String regionId) {
        int result = regionMapper.hasChildByRegionId(regionId);
        return result > 0;
    }

    /**
     * 查询地市是否存在用户
     *
     * @param regionId 地市ID
     * @return 结果 true 存在 false 不存在
     */
    @Override
    public boolean checkRegionExistUser(String regionId) {
        int result = regionMapper.checkRegionExistUser(regionId);
        return result > 0;
    }

    /**
     * 校验地市名称是否唯一
     *
     * @param region 地市信息
     * @return 结果
     */
    @Override
    public String checkRegionNameUnique(SysRegion region) {
        String regionId = StringUtils.isNull(region.getRegId()) ? "-1" : region.getRegId();
        SysRegion info = regionMapper.checkRegionNameUnique(region.getRegName(), region.getPregId());
        if (StringUtils.isNotNull(info) && info.getRegId() != regionId) {
            return UserConstants.NOT_UNIQUE;
        }
        return UserConstants.UNIQUE;
    }

    /**
     * 校验地市是否有数据权限
     *
     * @param regionId 地市id
     */
    @Override
    public void checkRegionDataScope(String regionId) {
        if (!SysUser.isAdmin(SecurityUtils.getUserId())) {
            SysRegion region = new SysRegion();
            region.setRegId(regionId);
            List<SysRegion> regions = SpringUtils.getAopProxy(this).selectRegionList(region);
            if (StringUtils.isEmpty(regions)) {
                throw new ServiceException("没有权限访问地市数据！");
            }
        }
    }

    /**
     * 新增保存地市信息
     *
     * @param region 地市信息
     * @return 结果
     */
    @Override
    public int insertRegion(SysRegion region) {
        SysRegion info = regionMapper.selectRegionById(region.getPregId());
        // 如果父节点不为正常状态,则不允许新增子节点
        if (!UserConstants.DEPT_NORMAL.equals(info.getStatus())) {
            throw new ServiceException("地市停用，不允许新增");
        }
        region.setAncestors(info.getAncestors() + "," + region.getPregId());
        return regionMapper.insertRegion(region);
    }

    /**
     * 修改保存地市信息
     *
     * @param region 地市信息
     * @return 结果
     */
    @Override
    public int updateRegion(SysRegion region) {
        SysRegion newParentRegion = regionMapper.selectRegionById(region.getPregId());
        SysRegion oldRegion = regionMapper.selectRegionById(region.getRegId());
        if (StringUtils.isNotNull(newParentRegion) && StringUtils.isNotNull(oldRegion)) {
            String newAncestors = newParentRegion.getAncestors() + "," + newParentRegion.getRegId();
            String oldAncestors = oldRegion.getAncestors();
            region.setAncestors(newAncestors);
            updateRegionChildren(region.getRegId(), newAncestors, oldAncestors);
        }
        int result = regionMapper.updateRegion(region);
        if (UserConstants.DEPT_NORMAL.equals(region.getStatus()) && StringUtils.isNotEmpty(region.getAncestors())
                && !StringUtils.equals("0", region.getAncestors())) {
            // 如果该地市是启用状态，则启用该地市的所有上级地市
            updateParentRegionStatusNormal(region);
        }
        return result;
    }

    /**
     * 修改该地市的父级地市状态
     *
     * @param region 当前地市
     */
    private void updateParentRegionStatusNormal(SysRegion region) {
        String ancestors = region.getAncestors();
        String[] regionIds = Convert.toStrArray(ancestors);
        regionMapper.updateRegionStatusNormal(regionIds);
    }

    /**
     * 修改子元素关系
     *
     * @param regionId     被修改的地市ID
     * @param newAncestors 新的父ID集合
     * @param oldAncestors 旧的父ID集合
     */
    public void updateRegionChildren(String regionId, String newAncestors, String oldAncestors) {
        List<SysRegion> children = regionMapper.selectChildrenRegionById(regionId);
        for (SysRegion child : children) {
            child.setAncestors(child.getAncestors().replaceFirst(oldAncestors, newAncestors));
        }
        if (children.size() > 0) {
            regionMapper.updateRegionChildren(children);
        }
    }

    /**
     * 删除地市管理信息
     *
     * @param regionId 地市ID
     * @return 结果
     */
    @Override
    public int deleteRegionById(String regionId) {
        return regionMapper.deleteRegionById(regionId);
    }

    /**
     * 获取地市下拉列表
     *
     * @return
     */
    @Override
    public List<SysRegion> getRegionList(String regId) {
        return regionMapper.getRegionList(regId);
    }

    @Override
    public List<SysRegion> selectChildrenRegionById(String regId) {
        return regionMapper.selectChildrenRegionById(regId);
    }

    /**
     * 递归列表
     */
    private void recursionFn(List<SysRegion> list, SysRegion t) {
        // 得到子节点列表
        List<SysRegion> childList = getChildList(list, t);
        t.setChildren(childList);
        for (SysRegion tChild : childList) {
            if (hasChild(list, tChild)) {
                recursionFn(list, tChild);
            }
        }
    }

    /**
     * 得到子节点列表
     */
    private List<SysRegion> getChildList(List<SysRegion> list, SysRegion t) {
        List<SysRegion> tlist = new ArrayList<SysRegion>();
        Iterator<SysRegion> it = list.iterator();
        while (it.hasNext()) {
            SysRegion n = (SysRegion) it.next();
            if (StringUtils.isNotNull(n.getPregId()) && n.getPregId().equals(t.getRegId())) {
                tlist.add(n);
            }
        }
        return tlist;
    }

    /**
     * 判断是否有子节点
     */
    private boolean hasChild(List<SysRegion> list, SysRegion t) {
        return getChildList(list, t).size() > 0;
    }

    /**
     * 获取当前用户的数据权限
     */
    @Override
    public List<String> getRegIds(String regId) {
        if ("1".equals(regId)) {
            regId = "220000";
        }
        if (hasChildByRegionId(regId)) {
            List<SysRegion> sysRegions = regionMapper.selectChildrenRegionById(regId);
            List<String> regIds = sysRegions.stream().map(sysRegion -> sysRegion.getRegId()).collect(Collectors.toList());
            return regIds;
        }
        List<String> list = new ArrayList<>();
        list.add(regId);
        return list;
    }


    /**
     * 拉取集团用户数据
     */
    @Override
    public void pullGroupUserData() {

    }

    /**
     * 项目启动时，初始化参数到缓存
     */
    @PostConstruct
    public void initRegionCache() {
        loadingConfigCache();
        System.out.println("行政区域，初始化参数到缓存成功");
    }

    /**
     * 重置参数缓存数据
     */
    @Override
    public void resetConfigCache() {
        clearRegionCache();
        loadingConfigCache();
    }

    /**
     * 加载参数缓存数据
     */
    public void loadingConfigCache() {
        List<SysRegion> sysRegionsList = regionMapper.selectRegionList(new SysRegion());
        for (SysRegion sysRegion : sysRegionsList) {
            redisCache.setCacheObject(getCacheKey(sysRegion.getRegName()), sysRegion.getRegId());
        }
    }

    /**
     * 设置cache key
     *
     * @param configKey 参数键
     * @return 缓存键key
     */
    private String getCacheKey(String configKey) {
        return CacheConstants.SYS_REGION_KEY + configKey;
    }

    /**
     * 清空参数缓存数据
     */
    @Override
    public void clearRegionCache() {
        Collection<String> keys = redisCache.keys(CacheConstants.SYS_REGION_KEY + "*");
        redisCache.deleteObject(keys);
    }

    /**
     * 根据键名查询参数配置信息
     *
     * @param configKey 参数key
     * @return 参数键值
     */
    @Override
    public String selectRegionByKey(String configKey) {
        String configValue = Convert.toStr(redisCache.getCacheObject(getCacheKey(configKey)));
        if (StringUtils.isNotEmpty(configValue)) {
            return configValue;
        }
        /*没有数据在根据值区去数据库查询  暂时不要先注释*/
        // String regionId = regionMapper.selectRegionId(configKey);
        // if (StringUtils.isNotNull(regionId)) {
        //     redisCache.setCacheObject(getCacheKey(configKey), regionId);
        //     return regionId;
        // }
        return StringUtils.EMPTY;
    }

}
